package com.jjc.android.util

import android.content.Context
import android.provider.Settings
import android.text.TextUtils
import com.alibaba.sdk.android.oss.OSS
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider
import com.jjc.android.util.OSSConfig
import com.alibaba.sdk.android.oss.ClientConfiguration
import com.alibaba.sdk.android.oss.OSSClient
import com.jjc.android.util.OssManager
import com.jjc.android.util.OssManager.OnUploadListener
import kotlin.Throws
import com.alibaba.sdk.android.oss.model.PutObjectRequest
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback
import com.alibaba.sdk.android.oss.model.PutObjectResult
import com.alibaba.sdk.android.oss.ClientException
import com.alibaba.sdk.android.oss.ServiceException
import io.reactivex.schedulers.Schedulers
import io.reactivex.android.schedulers.AndroidSchedulers
import com.jjc.android.App
import io.reactivex.Observable

class OssManager {
    private var mOSS: OSS? = null

    /**
     * 创建OSS对象
     */
    private fun getOSS(context: Context): OSS {
        if (mOSS == null) {
            val provider = OSSConfig.newCustomSignerCredentialProvider()
            val conf = ClientConfiguration()
            conf.connectionTimeout = 60 * 1000 // 连接超时，默认15秒
            conf.socketTimeout = 60 * 1000 // socket超时，默认15秒
            conf.maxConcurrentRequest = 5 // 最大并发请求书，默认5个
            conf.maxErrorRetry = 5 // 失败后最大重试次数，默认5次
            mOSS = OSSClient(context, endpoint, provider, conf)
        }
        return mOSS!!
    }

    /**
     * 图片上传
     *
     * @param context
     * @param uploadFilePath   图片的本地路径
     * @param onUploadListener 回调监听
     */
    fun upload(context: Context, uploadFilePath: String, onUploadListener: OnUploadListener?) {
        Observable.just(context)
            .map { context -> getOSS(context) }
            .map { oss -> // 创建上传的对象
                val put = PutObjectRequest(
                    bucketName,
                    getUUIDByRules32Image(uploadFilePath),
                    uploadFilePath
                )
                oss.asyncPutObject(
                    put,
                    object : OSSCompletedCallback<PutObjectRequest, PutObjectResult?> {
                        override fun onSuccess(
                            request: PutObjectRequest,
                            result: PutObjectResult?
                        ) {
                            if (onUploadListener == null) {
                                return
                            }
                            val objectKey = request.objectKey
                            onUploadListener.onSuccess(
                                uploadFilePath,
                                objectKey, baseUrl + objectKey
                            )
                        }

                        override fun onFailure(
                            request: PutObjectRequest,
                            clientException: ClientException,
                            serviceException: ServiceException
                        ) {
                            serviceException.printStackTrace()
                            clientException.printStackTrace()
                            if (onUploadListener == null) {
                                return
                            }
                            var error: String? = null
                            if (clientException != null) {
                                error = clientException.message
                            } else if (serviceException != null) {
                                error = serviceException.rawMessage
                            }
                            onUploadListener.onFailure(error)
                        }
                    })
                uploadFilePath
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe()
    }

    interface OnUploadListener {
        /**
         * 成功上传
         */
        fun onSuccess(uploadPath: String, objectKey: String, imageUrl: String)

        /**
         * 上传失败
         */
        fun onFailure(error: String?)
    }

    companion object {
        /**
         * 图片上传的地址
         */
        private const val endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
        private const val baseUrl = "https://home-detection.oss-cn-hangzhou.aliyuncs.com/"

        /**
         * Bucket是OSS上的命名空间
         * 问后台要的
         */
        private const val bucketName = "home-detection"
        private var mInstance: OssManager? = null
        val instance: OssManager
            get() {
                if (mInstance == null) {
                    synchronized(OssManager::class.java) { mInstance = OssManager() }
                }
                return mInstance!!
            }

        /**
         * 上传到后台的图片的名称
         */
        private fun getUUIDByRules32Image(uploadFilePath: String): String {
            val generateRandStr = androidId + "-" + System.currentTimeMillis()
            var houzhui = ""
            if (!TextUtils.isEmpty(uploadFilePath)) {
                houzhui =
                    uploadFilePath.substring(uploadFilePath.lastIndexOf("."), uploadFilePath.length)
            }
            return generateRandStr + houzhui
        }

        private val androidId: String
            private get() = Settings.Secure.getString(
                App.getContext().contentResolver,
                Settings.Secure.ANDROID_ID
            )
    }
}